use crate::search::{Doc2Index, DocFromIndexOuter, TanAction};
use crate::Request;
use crossbeam::channel::{Receiver, Sender};
use tide::{self, http::mime, Body, Middleware, Next, Response, StatusCode};
// use tempfile::TempDir;
use serde::Deserialize;
use std::sync::Arc;

#[derive(Debug, Clone)]
pub struct SearchMiddleware {
    tx: Arc<Sender<(TanAction, String, Option<Doc2Index>)>>,
    rx: Arc<Receiver<Vec<DocFromIndexOuter>>>,
}

impl SearchMiddleware {
    pub fn new(
        tx: Sender<(TanAction, String, Option<Doc2Index>)>,
        rx: Receiver<Vec<DocFromIndexOuter>>,
    ) -> Self {
        Self {
            tx: Arc::new(tx),
            rx: Arc::new(rx),
        }
    }
}

#[tide::utils::async_trait]
impl<State: Clone + Send + Sync + 'static> Middleware<State> for SearchMiddleware {
    async fn handle(&self, mut req: tide::Request<State>, next: Next<'_, State>) -> tide::Result {
        req.set_ext(self.clone());
        let res = next.run(req).await;
        Ok(res)
    }
}

#[derive(Deserialize)]
struct SearchQuery {
    s: String,
}

pub async fn search_get(req: Request) -> tide::Result {
    let sm: &SearchMiddleware = req.ext().unwrap();

    let input: SearchQuery = req.query()?;
    // let input = req.param("s").unwrap();
    sm.tx.send((TanAction::Query, input.s, None)).unwrap();

    let b = sm.rx.recv().unwrap();

    let re = Response::builder(StatusCode::Ok)
        .content_type(mime::JSON)
        .body(Body::from_json(&b)?)
        .build();

    Ok(re)
}
